﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using BorgExt.Behaviors;

namespace BorgExt.Forms.Behaviors
{
    public class ListBoxBinding<T> : Rule<T>
    {
        private readonly List<T> _composedItems;
        private readonly ListBox _listBox;
        private int _noUpdate;

        public ListBoxBinding(ListBox listBox)
        {
            _listBox = listBox;
            _listBox.SelectedValueChanged += SelectedValueChanged;
            _composedItems = new List<T>();
        }

        public override void AddCandidate(T item)
        {
            _listBox.Items.Add(item);
        }

        public override void Composed(T item)
        {
            _composedItems.Add(item);
            _noUpdate++;

            _listBox.SelectedItems.Add(item);
            _noUpdate--;
        }

        public override void Decomposed(T item)
        {
            _composedItems.Remove(item);
            _noUpdate++;

            _listBox.SelectedItems.Remove(item);
            _noUpdate--;
        }

        public override void RemoveCandidate(T item)
        {
            _listBox.Items.Remove(item);
        }

        private void SelectedValueChanged(object sender, EventArgs e)
        {
            if (_noUpdate > 0)
                return;

            var list1 = new List<T>(_composedItems.Count);
            list1.AddRange(_composedItems.Where(item => !_listBox.SelectedItems.Contains(item)));

            var list2 = new List<T>(_listBox.SelectedItems.Count);
            list2.AddRange(_listBox.SelectedItems.Cast<T>().Where(item => !_composedItems.Contains(item)));

            foreach (var element in list1)
                OnDecompose(element);

            foreach (var element in list2)
                OnCompose(element);
        }
    }
}

